www.gusucode.com > VC++ SkinCtrls窗体常用控件换肤程序-源码程序 > VC++ SkinCtrls窗体常用控件换肤程序-源码程序/code/Shared/RoundCorner.cpp
// Roundcnr.cpp: implementation of the CRoundCorner class. // Download by http://www.NewXing.com ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "Roundcorner.h" #include "syscolors.h" #include <math.h> #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif const double Pi = 3.141592654; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// enum { COLD, DOWN , HOT }; struct Corner { Corner() { bInfillBetween = FALSE; } CPoint ptQuadrant; CPoint ptOriginOffset; COLORREF crFrom, crTo; int nAngleFrom, nAngleTo; BOOL bInfillBetween; }; // precalculated color factors float fHiliteFactor[] = { 0.2f, 0.35f, 0.29f, 0.24f, 0.18f, 0.12f, 0.06f }; float fShadowFactor[] = { 0.7f, 0.75f, 0.81f, 0.85f, 0.88f, 0.91f, 0.95f }; const int NUMFACTORS = sizeof(fHiliteFactor) / sizeof(float); ////////////////////////////////////////////////////////////////////// CRoundCorner::CRoundCorner(CWnd* pWnd, int nRadius, COLORREF crBkgnd) { ASSERT (pWnd); m_pWnd = pWnd; m_nRadius = max(0, nRadius); m_crBkgnd = crBkgnd; } CRoundCorner::~CRoundCorner() { } void CRoundCorner::Draw(int nCorners, DWORD dwStyle) { ASSERT (m_pWnd); if (!m_pWnd) return; CRect rWnd; m_pWnd->GetWindowRect(rWnd); CWindowDC dc(m_pWnd); Draw(&dc, rWnd, m_nRadius, nCorners, dwStyle, m_crBkgnd); } // static version void CRoundCorner::Draw(CDC* pDC, LPRECT pRect, int nRadius, int nCorners, DWORD dwStyle, COLORREF crBkgnd) { // special case: if cold and the backgnd color // has not been specified then nothing to draw int nState = (dwStyle & RC_DOWN) ? DOWN : (dwStyle & RC_UP) ? HOT : COLD; if (nState == COLD && crBkgnd == -1) return; // edge style if (dwStyle & RC_RENDER) { ASSERT (dwStyle & RC_EDGES); if (!(dwStyle & RC_EDGES)) return; if (crBkgnd == (COLORREF)-1) crBkgnd = GetColor(COLOR_3DFACE, -1); } CRect rect(pRect); // BOOL bDefBtn = (dwStyle & RC_DEFBTN) && (dwStyle & RC_EDGES); // if (bDefBtn) // rect.DeflateRect(1, 1); rect.right--; rect.bottom--; nRadius = max(0, nRadius); // the maximum allowable radius depends one which Corners are to drawn int nMaxRadius = 0; BOOL bTopLeft = (nCorners & RC_TOPLEFT); BOOL bTopRight = (nCorners & RC_TOPRIGHT); BOOL bBottomLeft = (nCorners & RC_BOTTOMLEFT); BOOL bBottomRight = (nCorners & RC_BOTTOMRIGHT); if (bTopLeft && bTopRight && !bBottomLeft && !bBottomRight) nMaxRadius = min(rect.Height(), rect.Width() / 2); else if (!bTopLeft && !bTopRight && bBottomLeft && bBottomRight) nMaxRadius = min(rect.Height(), rect.Width() / 2); // same else if (bTopLeft && bBottomLeft && !bTopRight && !bBottomRight) nMaxRadius = min(rect.Width(), rect.Height() / 2); else if (!bTopLeft && !bBottomLeft && bTopRight && bBottomRight) nMaxRadius = min(rect.Width(), rect.Height() / 2); // same else nMaxRadius = min(rect.Width(), rect.Height()) / 2; nRadius = min(nRadius, nMaxRadius); if (nRadius) { // draw the Corners first and then the connecting edges if (bTopLeft) DrawTopLeft(pDC, rect, nRadius, dwStyle, crBkgnd); if (bTopRight) DrawTopRight(pDC, rect, nRadius, dwStyle, crBkgnd); if (bBottomRight) DrawBottomRight(pDC, rect, nRadius, dwStyle, crBkgnd); if (bBottomLeft) DrawBottomLeft(pDC, rect, nRadius, dwStyle, crBkgnd); } // now the edges DrawEdges(pDC, rect, nRadius, nCorners, dwStyle, crBkgnd); // now the def button border /* if (bDefBtn) { rect.InflateRect(1, 1); DrawDefBtnBorder(pDC, rect, nRadius, nCorners); } */ } void CRoundCorner::DrawDefBtnBorder(CDC* pDC, LPRECT pRect, int nRadius, int nCorners) { if (!nRadius || !nCorners) { pDC->Draw3dRect(pRect, 0, 0); return; } BOOL bTopLeft = (nCorners & RC_TOPLEFT); BOOL bTopRight = (nCorners & RC_TOPRIGHT); BOOL bBottomLeft = (nCorners & RC_BOTTOMLEFT); BOOL bBottomRight = (nCorners & RC_BOTTOMRIGHT); Corner cnr; CRect rect(pRect); nRadius = max(0, nRadius); nRadius = min(nRadius, min(rect.Width(), rect.Height()) / 2); cnr.crFrom = cnr.crTo = 0; cnr.bInfillBetween = TRUE; // top left if (bTopLeft) { cnr.ptQuadrant = CPoint(-1, 1); cnr.ptOriginOffset = CPoint(rect.left + nRadius, rect.top + nRadius); cnr.nAngleFrom = 270; cnr.nAngleTo = 360; DrawCorner(pDC, nRadius, &cnr); } // top right if (bTopRight) { cnr.ptQuadrant = CPoint(1, 1); cnr.ptOriginOffset = CPoint(rect.right - nRadius, rect.top + nRadius); cnr.nAngleFrom = 0; cnr.nAngleTo = 90; DrawCorner(pDC, nRadius, &cnr); } // bottom left if (bBottomLeft) { cnr.ptQuadrant = CPoint(-1, -1); cnr.ptOriginOffset = CPoint(rect.left + nRadius, rect.bottom - nRadius); cnr.nAngleFrom = 180; cnr.nAngleTo = 270; DrawCorner(pDC, nRadius, &cnr); } // bottom right if (bBottomRight) { cnr.ptQuadrant = CPoint(1, -1); cnr.ptOriginOffset = CPoint(rect.right - nRadius, rect.bottom - nRadius); cnr.nAngleFrom = 90; cnr.nAngleTo = 180; DrawCorner(pDC, nRadius, &cnr); } // edges // top CRect rHLine(rect.left + (bTopLeft ? nRadius : 0), rect.top, rect.right - (bTopRight ? nRadius: 0), rect.top + 1); // left CRect rVLine(rect.left, rect.top + (bTopLeft ? nRadius : 0), rect.left + 1, rect.bottom - (bBottomLeft ? nRadius : 0)); pDC->FillSolidRect(rHLine, 0); pDC->FillSolidRect(rVLine, 0); // bottom rHLine.SetRect(rect.left + (bBottomLeft ? nRadius : 0), rect.bottom, rect.right - ((bBottomRight && nRadius) ? nRadius : -1), rect.bottom + 1); // right rVLine.SetRect(rect.right, rect.top + (bTopRight ? nRadius : 0), rect.right + 1, rect.bottom - ((bBottomRight && nRadius) ? nRadius : -1)); pDC->FillSolidRect(rHLine, 0); pDC->FillSolidRect(rVLine, 0); } void CRoundCorner::DrawEdges(CDC* pDC, LPRECT pRect, int nRadius, int nCorners, DWORD dwStyle, COLORREF crBkgnd) { if (!(dwStyle & RC_EDGES)) // sanity check return; BOOL bRender = (dwStyle & RC_RENDER); BOOL bThin = !bRender && (dwStyle & RC_THIN); int nState = (dwStyle & RC_DOWN) ? DOWN : (dwStyle & RC_UP) ? HOT : COLD; // if cold and the backgnd color has not been set then nothing to draw if (nState == COLD && crBkgnd == -1) return; BOOL bTopLeft = (nCorners & RC_TOPLEFT); BOOL bTopRight = (nCorners & RC_TOPRIGHT); BOOL bBottomLeft = (nCorners & RC_BOTTOMLEFT); BOOL bBottomRight = (nCorners & RC_BOTTOMRIGHT); CRect rect(pRect); COLORREF color; nRadius = max(0, nRadius); nRadius = min(nRadius, min(rect.Width(), rect.Height()) / 2); // top CRect rHLine(rect.left + (bTopLeft ? nRadius : 0), rect.top, rect.right - (bTopRight ? nRadius: 0), rect.top + 1); // left CRect rVLine(rect.left, rect.top + (bTopLeft ? nRadius : 0), rect.left + 1, rect.bottom - (bBottomLeft ? nRadius : 0)); if (bRender && crBkgnd != -1) { int nLine = 0; int nMaxLine = nRadius ? min(NUMFACTORS, nRadius) : min(NUMFACTORS, min(rect.Width(), rect.Height()) / 2); do { int nFactor = (nLine * NUMFACTORS) / nMaxLine; COLORREF color = (nState == DOWN) ? Darker(crBkgnd, fShadowFactor[nFactor]) : (nState == HOT) ? Lighter(crBkgnd, fHiliteFactor[nFactor]) : crBkgnd; pDC->FillSolidRect(rHLine, color); pDC->FillSolidRect(rVLine, color); rHLine.OffsetRect(0, 1); rVLine.OffsetRect(1, 0); if (!nRadius) { // shorten by one pixel rHLine.DeflateRect(1, 0); rVLine.DeflateRect(0, 1); } nLine++; } while (nLine < nMaxLine); } else { if (!bThin) { color = (nState == DOWN) ? GetColor(COLOR_3DSHADOW, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DFACE, crBkgnd) : crBkgnd; pDC->FillSolidRect(rHLine, color); pDC->FillSolidRect(rVLine, color); rHLine.OffsetRect(0, 1); rVLine.OffsetRect(1, 0); if (!nRadius) { // shorten by one pixel rHLine.DeflateRect(1, 0); rVLine.DeflateRect(0, 1); } color = (nState == DOWN) ? GetColor(COLOR_3DDKSHADOW, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DHILIGHT, crBkgnd) : crBkgnd; } else { color = (nState == DOWN) ? GetColor(COLOR_3DSHADOW, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DHILIGHT, crBkgnd) : crBkgnd; } pDC->FillSolidRect(rHLine, color); pDC->FillSolidRect(rVLine, color); } // bottom rHLine.SetRect(rect.left + (bBottomLeft ? nRadius : 0), rect.bottom, rect.right - ((bBottomRight && nRadius) ? nRadius : -1), rect.bottom + 1); // right rVLine.SetRect(rect.right, rect.top + (bTopRight ? nRadius : 0), rect.right + 1, rect.bottom - ((bBottomRight && nRadius) ? nRadius : -1)); if (bRender && crBkgnd != -1) { int nLine = 0; int nMaxLine = nRadius ? min(NUMFACTORS, nRadius) : min(NUMFACTORS, min(rect.Width(), rect.Height()) / 2); do { int nFactor = (nLine * NUMFACTORS) / nMaxLine; COLORREF color = (nState == DOWN) ? Lighter(crBkgnd, fHiliteFactor[nFactor]) : (nState == HOT) ? Darker(crBkgnd, fShadowFactor[nFactor]) : crBkgnd; pDC->FillSolidRect(rHLine, color); pDC->FillSolidRect(rVLine, color); rHLine.OffsetRect(0, -1); rVLine.OffsetRect(-1, 0); if (!nRadius) { // shorten by one pixel rHLine.DeflateRect(1, 0); rVLine.DeflateRect(0, 1); } nLine++; } while (nLine < nMaxLine); } else { if (!bThin) { color = (nState == DOWN) ? GetColor(COLOR_3DHILIGHT, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DDKSHADOW, crBkgnd) : crBkgnd; pDC->FillSolidRect(rHLine, color); pDC->FillSolidRect(rVLine, color); rHLine.OffsetRect(0, -1); rVLine.OffsetRect(-1, 0); if (!nRadius) { // shorten by one pixel rHLine.DeflateRect(1, 0); rVLine.DeflateRect(0, 1); } color = (nState == DOWN) ? GetColor(COLOR_3DFACE, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DSHADOW, crBkgnd) : crBkgnd; } else { color = (nState == DOWN) ? GetColor(COLOR_3DHIGHLIGHT, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DSHADOW, crBkgnd) : crBkgnd; } pDC->FillSolidRect(rHLine, color); pDC->FillSolidRect(rVLine, color); } } COLORREF CRoundCorner::GetColor(int nAngle, int nDegreesFrom, int nDegreesTo, COLORREF crFrom, COLORREF crTo) { if (crFrom == crTo) return crFrom; COLORREF crResult = RGB(0, 0, 0); if (nDegreesFrom > nDegreesTo) nDegreesTo += 360; ASSERT (nAngle >= nDegreesFrom && nAngle <= nDegreesTo); if (nAngle >= nDegreesFrom && nAngle <= nDegreesTo) { // all this does is to approximate the averageof the two colors // at the point being queried BYTE byRedFrom = GetRValue(crFrom); BYTE byGreenFrom = GetGValue(crFrom); BYTE byBlueFrom = GetBValue(crFrom); BYTE byRedTo = GetRValue(crTo); BYTE byGreenTo = GetGValue(crTo); BYTE byBlueTo = GetBValue(crTo); int nOffset = nAngle - nDegreesFrom; int nDiff = nDegreesTo - nDegreesFrom; BYTE byRedResult = (byRedFrom * (nDiff - nOffset) + byRedTo * nOffset) / nDiff; BYTE byGreenResult = (byGreenFrom * (nDiff - nOffset) + byGreenTo * nOffset) / nDiff; BYTE byBlueResult = (byBlueFrom * (nDiff - nOffset) + byBlueTo * nOffset) / nDiff; crResult = RGB(byRedResult, byGreenResult, byBlueResult); } return crResult; } void CRoundCorner::DrawTopLeft(CDC* pDC, LPRECT pRect, int nRadius, DWORD dwStyle, COLORREF crBkgnd) { if (!nRadius) return; BOOL bRender = (dwStyle & RC_RENDER) && (crBkgnd != -1); BOOL bThin = !bRender && (dwStyle & RC_THIN); int nState = (dwStyle & RC_DOWN) ? DOWN : (dwStyle & RC_UP) ? HOT : COLD; Corner cnr; cnr.ptQuadrant = CPoint(-1, 1); cnr.ptOriginOffset = CPoint(pRect->left + nRadius, pRect->top + nRadius); cnr.nAngleFrom = 270; cnr.nAngleTo = 360; if (bRender) { int nLine = 0; int nMaxLine = min(NUMFACTORS, nRadius); cnr.bInfillBetween = TRUE; do { int nFactor = (nLine * NUMFACTORS) / nMaxLine; cnr.crFrom = (nState == DOWN) ? Darker(crBkgnd, fShadowFactor[nFactor]) : (nState == HOT) ? Lighter(crBkgnd, fHiliteFactor[nFactor]) : crBkgnd; cnr.crTo = cnr.crFrom; DrawCorner(pDC, nRadius, &cnr); nRadius--; nLine++; } while (nLine < nMaxLine); } else { if (!bThin) { cnr.crFrom = (nState == DOWN) ? GetColor(COLOR_3DSHADOW, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DFACE, crBkgnd) : crBkgnd; cnr.crTo = cnr.crFrom; cnr.bInfillBetween = TRUE; DrawCorner(pDC, nRadius, &cnr); nRadius--; cnr.crFrom = (nState == DOWN) ? GetColor(COLOR_3DDKSHADOW, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DHILIGHT, crBkgnd) : crBkgnd; } else { cnr.crFrom = (nState == DOWN) ? GetColor(COLOR_3DSHADOW, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DHILIGHT, crBkgnd) : crBkgnd; } cnr.crTo = cnr.crFrom; cnr.bInfillBetween = FALSE; DrawCorner(pDC, nRadius, &cnr); } } void CRoundCorner::DrawTopRight(CDC* pDC, LPRECT pRect, int nRadius, DWORD dwStyle, COLORREF crBkgnd) { if (!nRadius) return; BOOL bRender = (dwStyle & RC_RENDER) && (crBkgnd != -1); BOOL bThin = !bRender && (dwStyle & RC_THIN); int nState = (dwStyle & RC_DOWN) ? DOWN : (dwStyle & RC_UP) ? HOT : COLD; Corner cnr; cnr.ptQuadrant = CPoint(1, 1); cnr.ptOriginOffset = CPoint(pRect->right - nRadius, pRect->top + nRadius); cnr.nAngleFrom = 0; cnr.nAngleTo = 90; if (bRender) { int nLine = 0; int nMaxLine = min(NUMFACTORS, nRadius); cnr.bInfillBetween = TRUE; do { int nFactor = (nLine * NUMFACTORS) / nMaxLine; cnr.crFrom = (nState == DOWN) ? Darker(crBkgnd, fShadowFactor[nFactor]) : (nState == HOT) ? Lighter(crBkgnd, fHiliteFactor[nFactor]) : crBkgnd; cnr.crTo = (nState == DOWN) ? Lighter(crBkgnd, fHiliteFactor[nFactor]) : (nState == HOT) ? Darker(crBkgnd, fShadowFactor[nFactor]) : crBkgnd; DrawCorner(pDC, nRadius, &cnr); nRadius--; nLine++; } while (nLine < nMaxLine); } else { if (!bThin) { cnr.crFrom = (nState == DOWN) ? GetColor(COLOR_3DSHADOW, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DFACE, crBkgnd) : crBkgnd; cnr.crTo = (nState == DOWN) ? GetColor(COLOR_3DFACE, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DSHADOW, crBkgnd) : crBkgnd; cnr.bInfillBetween = TRUE; DrawCorner(pDC, nRadius, &cnr); nRadius--; cnr.crFrom = (nState == DOWN) ? GetColor(COLOR_3DDKSHADOW, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DHILIGHT, crBkgnd) : crBkgnd; cnr.crTo = (nState == DOWN) ? GetColor(COLOR_3DHILIGHT, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DDKSHADOW, crBkgnd) : crBkgnd; } else { cnr.crFrom = (nState == DOWN) ? GetColor(COLOR_3DSHADOW, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DHILIGHT, crBkgnd) : crBkgnd; cnr.crTo = (nState == DOWN) ? GetColor(COLOR_3DHILIGHT, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DSHADOW, crBkgnd) : crBkgnd; } cnr.bInfillBetween = FALSE; DrawCorner(pDC, nRadius, &cnr); } } void CRoundCorner::DrawBottomLeft(CDC* pDC, LPRECT pRect, int nRadius, DWORD dwStyle, COLORREF crBkgnd) { if (!nRadius) return; BOOL bRender = (dwStyle & RC_RENDER) && (crBkgnd != -1); BOOL bThin = !bRender && (dwStyle & RC_THIN); int nState = (dwStyle & RC_DOWN) ? DOWN : (dwStyle & RC_UP) ? HOT : COLD; Corner cnr; cnr.ptQuadrant = CPoint(-1, -1); cnr.ptOriginOffset = CPoint(pRect->left + nRadius, pRect->bottom - nRadius); cnr.nAngleFrom = 180; cnr.nAngleTo = 270; if (bRender) { int nLine = 0; int nMaxLine = min(NUMFACTORS, nRadius); cnr.bInfillBetween = TRUE; do { int nFactor = (nLine * NUMFACTORS) / nMaxLine; cnr.crFrom = (nState == DOWN) ? Lighter(crBkgnd, fHiliteFactor[nFactor]) : (nState == HOT) ? Darker(crBkgnd, fShadowFactor[nFactor]) : crBkgnd; cnr.crTo = (nState == DOWN) ? Darker(crBkgnd, fShadowFactor[nFactor]) : (nState == HOT) ? Lighter(crBkgnd, fHiliteFactor[nFactor]) : crBkgnd; DrawCorner(pDC, nRadius, &cnr); nRadius--; nLine++; } while (nLine < nMaxLine); } else { if (!bThin) { cnr.crFrom = (nState == DOWN) ? GetColor(COLOR_3DHILIGHT, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DDKSHADOW, crBkgnd) : crBkgnd; cnr.crTo = (nState == DOWN) ? GetColor(COLOR_3DSHADOW, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DFACE, crBkgnd) : crBkgnd; cnr.bInfillBetween = TRUE; DrawCorner(pDC, nRadius, &cnr); nRadius--; cnr.crFrom = (nState == DOWN) ? GetColor(COLOR_3DFACE, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DSHADOW, crBkgnd) : crBkgnd; cnr.crTo = (nState == DOWN) ? GetColor(COLOR_3DDKSHADOW, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DHILIGHT, crBkgnd) : crBkgnd; } else { cnr.crFrom = (nState == DOWN) ? GetColor(COLOR_3DHIGHLIGHT, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DSHADOW, crBkgnd) : crBkgnd; cnr.crTo = (nState == DOWN) ? GetColor(COLOR_3DSHADOW, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DHILIGHT, crBkgnd) : crBkgnd; } cnr.bInfillBetween = FALSE; DrawCorner(pDC, nRadius, &cnr); } } void CRoundCorner::DrawBottomRight(CDC* pDC, LPRECT pRect, int nRadius, DWORD dwStyle, COLORREF crBkgnd) { if (!nRadius) return; BOOL bRender = (dwStyle & RC_RENDER) && (crBkgnd != -1); BOOL bThin = !bRender && (dwStyle & RC_THIN); int nState = (dwStyle & RC_DOWN) ? DOWN : (dwStyle & RC_UP) ? HOT : COLD; Corner cnr; cnr.ptQuadrant = CPoint(1, -1); cnr.ptOriginOffset = CPoint(pRect->right - nRadius, pRect->bottom - nRadius); cnr.nAngleFrom = 90; cnr.nAngleTo = 180; if (bRender) { int nLine = 0; int nMaxLine = min(NUMFACTORS, nRadius); cnr.bInfillBetween = TRUE; do { int nFactor = (nLine * NUMFACTORS) / nMaxLine; cnr.crFrom = (nState == DOWN) ? Lighter(crBkgnd, fHiliteFactor[nFactor]) : (nState == HOT) ? Darker(crBkgnd, fShadowFactor[nFactor]) : crBkgnd; cnr.crTo = cnr.crFrom; DrawCorner(pDC, nRadius, &cnr); nRadius--; nLine++; } while (nLine < nMaxLine); } else { if (!bThin) { cnr.crFrom = (nState == DOWN) ? GetColor(COLOR_3DHILIGHT, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DDKSHADOW, crBkgnd) : crBkgnd; cnr.crTo = cnr.crFrom; cnr.bInfillBetween = TRUE; DrawCorner(pDC, nRadius, &cnr); nRadius--; cnr.crFrom = (nState == DOWN) ? GetColor(COLOR_3DFACE, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DSHADOW, crBkgnd) : crBkgnd; } else { cnr.crFrom = (nState == DOWN) ? GetColor(COLOR_3DHIGHLIGHT, crBkgnd) : (nState == HOT) ? GetColor(COLOR_3DSHADOW, crBkgnd) : crBkgnd; } cnr.crTo = cnr.crFrom; cnr.bInfillBetween = FALSE; DrawCorner(pDC, nRadius, &cnr); } } void CRoundCorner::DrawCorner(CDC* pDC, int nRadius, Corner* pCorner) { CPoint ptBase(0, nRadius); int nDecision = 1 - nRadius; while (ptBase.y >= ptBase.x) { // translate to target quadrant CPoint ptQuadrant(ptBase.x * pCorner->ptQuadrant.x, ptBase.y * pCorner->ptQuadrant.y); // flip to adjacent octant int nFlip = ((pCorner->ptQuadrant.x > 0 && pCorner->ptQuadrant.y > 0) || (pCorner->ptQuadrant.x < 0 && pCorner->ptQuadrant.y < 0)) ? 1 : -1; CPoint ptOctant(ptQuadrant.y * nFlip, ptQuadrant.x * nFlip); // adjust y value for MM_TEXT ptQuadrant.y = -ptQuadrant.y; ptOctant.y = -ptOctant.y; // offset to actual position ptQuadrant.Offset(pCorner->ptOriginOffset); ptOctant.Offset(pCorner->ptOriginOffset); // draw pixels double dRad = asin((double)ptBase.x / nRadius); int nAngle = (int)((dRad * 180) / Pi); COLORREF crQuadrant = GetColor(pCorner->nAngleFrom + nAngle, pCorner->nAngleFrom, pCorner->nAngleTo, pCorner->crFrom, pCorner->crTo); pDC->SetPixelV(ptQuadrant, crQuadrant); COLORREF crOctant = GetColor(pCorner->nAngleTo - nAngle, pCorner->nAngleFrom, pCorner->nAngleTo, pCorner->crFrom, pCorner->crTo); pDC->SetPixelV(ptOctant, crOctant); // next iteration if (nDecision < 0) { nDecision += (2 * ptBase.x + 3); ptBase.x++; } else { nDecision += (2 * (ptBase.x - ptBase.y) + 5); ptBase.y--; ptBase.x++; if (pCorner->bInfillBetween) { // draw fill in pixel ptQuadrant.y += pCorner->ptQuadrant.y; ptOctant.x -= pCorner->ptQuadrant.x; // draw pixels pDC->SetPixelV(ptQuadrant, crQuadrant); pDC->SetPixelV(ptOctant, crOctant); } } } } ////////////////////////////////// COLORREF CRoundCorner::GetColor(int nColor, COLORREF crBase) { if (crBase != -1) { switch (nColor) { case COLOR_3DHILIGHT: return Lighter(crBase); case COLOR_3DSHADOW: return Darker(crBase, 0.75f); case COLOR_3DDKSHADOW: return Darker(crBase, 0.2f); case COLOR_3DFACE: // case COLOR_PARENTBKGND: return crBase; } } // default if (nColor == COLOR_PARENTBKGND) nColor = COLOR_3DFACE; return ::GetSysColor(nColor); } COLORREF CRoundCorner::Darker(COLORREF crBase, float fFactor) { if (fFactor <= 0.0f) return 0; else if (fFactor >= 1.0f) return crBase; fFactor = min(fFactor, 1.0f); fFactor = max(fFactor, 0.0f); BYTE bRed, bBlue, bGreen; BYTE bRedShadow, bBlueShadow, bGreenShadow; bRed = GetRValue(crBase); bBlue = GetBValue(crBase); bGreen = GetGValue(crBase); bRedShadow = (BYTE)(bRed * fFactor) + (bRed % 2); bBlueShadow = (BYTE)(bBlue * fFactor) + (bBlue % 2); bGreenShadow = (BYTE)(bGreen * fFactor) + (bGreen % 2); return RGB(bRedShadow, bGreenShadow, bBlueShadow); } COLORREF CRoundCorner::Lighter(COLORREF crBase, float fFactor) { if (fFactor <= 0.0f) return crBase; else if (fFactor >= 1.0f) return RGB(255, 255, 255); fFactor = min(fFactor, 1.0f); fFactor = max(fFactor, 0.0f); BYTE bRed, bBlue, bGreen; BYTE bRedHilite, bBlueHilite, bGreenHilite; bRed = GetRValue(crBase); bBlue = GetBValue(crBase); bGreen = GetGValue(crBase); bRedHilite = min(255, bRed + (BYTE)(255 * fFactor)); bBlueHilite = min(255, bBlue + (BYTE)(255 * fFactor)); bGreenHilite = min(255, bGreen + (BYTE)(255 * fFactor)); return RGB(bRedHilite, bGreenHilite, bBlueHilite); }